﻿using Microsoft.AspNetCore.Mvc;
using MiniFox.Components;
using MiniFox.Infrastructure;
using MiniFox.Log;
using MiniFox.Platform.File.Models;
using MiniFox.Platform.File.Services;
using MiniFox.Resources;
using MiniFox.Utility;
using MiniFox.Web;
using MiniFox.Web.Infrastructure;
using System.ComponentModel.DataAnnotations;

namespace MiniFox.Platform.File.Web
{
    /// <summary>
    /// 文件处理控制器
    /// </summary>
    [PublicAccessible]
    public class FileController : BinaryControllerBase
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="group"></param>
        /// <returns></returns>
        protected virtual IFileService CreateComponent(string group)
        {
            IFileService _component = ComponentFactory.GetComponent<IFileService>(group);
            return _component;
        }

        private DownloadResult CreateDownloadResult(FileData fileData, string routeName, string group, string dispositionType)
        {
            var url = this.Url.RouteUrl(routeName, new
            {
                controller = "file",
                action = "load",
                group
            });
            return new DownloadResult
            {
                FileData = fileData,
                Uri = WebUtil.BuildFullUrl(this.Request.GetFullApplicationPath(), url, new
                {
                    fileId = fileData.FileId,
                    dispositionType
                })

            };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileDatas"></param>
        /// <param name="routeName"></param>
        /// <param name="group"></param>
        /// <returns></returns>
        protected virtual IEnumerable<DownloadResult> CreateDownload(IEnumerable<FileData> fileDatas, string routeName, string group)
        {
            return fileDatas.Select(f => { return CreateDownloadResult(f, routeName, group, null); });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileData"></param>
        /// <param name="routeName"></param>
        /// <param name="group"></param>
        /// <param name="preDownload"></param>
        /// <param name="dispositionType"></param>
        /// <returns></returns>
        protected virtual IActionResult CreateDownload(FileData fileData, string routeName, string group, bool preDownload, string dispositionType)
        {
            if (preDownload)
            {
                var result = CreateDownloadResult(fileData, routeName, group, dispositionType);
                return this.ResponseResult(result.CreateResponse());
            }
            else
            {
                var result = this.Execute(fileData.Data, fileData.ContentType, fileData.FileName, dispositionType);
                return result;
            }
        }
        /// <summary>
        /// 下载文件(get url: /file/load/{group}?fileId=?&amp;dispositionType=?)
        /// </summary>
        /// <param name="group">资源管理组名</param>
        /// <param name="fileId">文件id</param>
        /// <param name="dispositionType"></param>
        /// <returns></returns>
        [HttpGet, NoLog]
        public async Task<IActionResult> LoadAsync([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"),  FromRoute(Name = GlobalKey.NAME)] string group,
            [Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"), FromQuery] string fileId,
            [FromQuery] string? dispositionType)
        {
            var request = new DownloadSingleRequest { FileID = fileId, DispositionType = dispositionType };
            return await LoadAsync(group, request);
        }
        /// <summary>
        /// 下载文件(post url: /file/load/{group})
        /// </summary>
        /// <param name="group">资源管理组名</param>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost, NoLog]
        public async Task<IActionResult> LoadAsync([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"),  FromRoute(Name = GlobalKey.NAME)] string group,
            [FromBody] DownloadSingleRequest request)
        {
            var component = this.CreateComponent(group);
            var fileData = await component.LoadAsync(request.FileID);
            return CreateDownload(fileData, component.RouteName, group, component.PreDownload, request.DispositionType);
        }
        /// <summary>
        /// 下载文件(post url: /file/loadbatch/{group})
        /// </summary>
        /// <param name="group">资源管理组名</param>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> LoadBatchAsync([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"),  FromRoute(Name = GlobalKey.NAME)] string group,
            [FromBody] DownloadBatchRequest request)
        {
            var component = this.CreateComponent(group);
            var fileDatas = component.LoadBatch(request.FileID);
            var zip = await component.CreateZipAsync(fileDatas, request.FileName);
            return CreateDownload(zip, component.RouteName, group, component.PreDownload, null);
        }
        /// <summary>
        /// 获取文件(post url: /file/query/{group})
        /// </summary>
        /// <param name="group">资源管理组名</param>
        /// <param name="path"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        [HttpGet]
        public Response<IEnumerable<DownloadResult>> GetFiles([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"), FromRoute(Name = GlobalKey.NAME)] string group,
            [FromQuery] string path, [FromQuery] int? top)
        {
            var component = this.CreateComponent(group);
            var files = component.GetFiles(path, top);
            var result = this.CreateDownload(files, component.RouteName, group);
            return result.CreateResponse();
        }
        /// <summary>
        /// 获取文件(post url: /file/query/{group})
        /// </summary>
        /// <param name="group">资源管理组名</param>
        /// <param name="fileIds"></param>
        /// <returns></returns>
        [HttpPost]
        public Response<IEnumerable<DownloadResult>> GetFiles([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"),  FromRoute(Name = GlobalKey.NAME)] string group,
            [FromBody] string[] fileIds)
        {
            var component = this.CreateComponent(group);
            var files = component.Query(fileIds);
            var result = this.CreateDownload(files, component.RouteName, group);
            return result.CreateResponse();
        }
        ///// <summary>
        ///// 获取文件(get url: /file/query/{group})
        ///// </summary>
        ///// <param name="group">资源管理组名</param>
        ///// <param name="folderId"></param>
        ///// <returns></returns>
        //[HttpGet]
        //public Response<IEnumerable<DownloadResult>> Query([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"), FromRoute(Name = GlobalKey.NAME)] string group,
        //    [FromQuery] string folderId)
        //{
        //    var component = this.CreateComponent(group);
        //    var files = component.Query(folderId);
        //    var result = this.CreateDownload(files, component.RouteName, group);
        //    return result.CreateResponse();
        //}
        /// <summary>
        /// 查询文件(post url: /file/query/{group})
        /// </summary>
        /// <param name="group">资源管理组名</param>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public Response<ResultObject<IEnumerable<FileData>>> Query([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"), FromRoute(Name = GlobalKey.NAME)] string group,
            [FromBody] PagedQueryObject<FileQuery> request)
        {
            ArgumentException.ThrowIfNullOrEmpty(group);
            ArgumentNullException.ThrowIfNull(request);
            var component = this.CreateComponent(group);
            var result = component.Query(request);
            return result.CreateResponse();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="group"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public Response CheckFile([Required(ErrorMessageResourceType = typeof(CommonMessages), ErrorMessageResourceName = "MSG_CommonRequired"), FromRoute(Name = GlobalKey.NAME)] string group,
            [FromBody] CheckFileRequest request)
        {
            ArgumentException.ThrowIfNullOrEmpty(group);
            ArgumentNullException.ThrowIfNull(request);
            var component = this.CreateComponent(group);
            component.CheckFileAvaliable(request);
            return new();
        }
    }
}
